package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.huanxin.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.*;
import com.itheima.domain.db.Freeze;
import com.itheima.domain.mongo.UserLike;
import com.itheima.service.db.*;
import com.itheima.domain.mongo.UserLike;
import com.itheima.service.db.FreezeService;
import com.itheima.service.mongo.FriendService;
import com.itheima.service.mongo.MovementService;
import com.itheima.service.mongo.UserLikeService;
import com.itheima.service.mongo.VisitorService;
import com.itheima.service.mongo.FriendService;
import com.itheima.service.mongo.MovementService;
import com.itheima.service.mongo.UserLikeService;
import com.itheima.service.mongo.VisitorService;
import com.itheima.util.ConstantUtil;
import com.itheima.util.JwtUtil;
import com.itheima.vo.ErrorResult;
import com.itheima.vo.PageBeanVo;
import com.itheima.vo.PageBeanVo;
import com.itheima.vo.UserInfoVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class UserManager {

    @DubboReference
    private UserService userService;

    // 保存用户
    public ResponseEntity save(User user) {
        return ResponseEntity.ok(userService.save(user));
    }

    // 查询用户
    public ResponseEntity findByPhone(String phone) {
        int i = 1 / 0;
        User user = userService.findByPhone(phone);
        return ResponseEntity.ok(user);
    }

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 发送短信验证码
    public void sendSms(String phone) {
        // 1.生成6位随机数
        String smsCode = RandomUtil.randomNumbers(6);
        smsCode = "123456";

        // 2.调用阿里云发送
        // smsTemplate.sendSms(phone, smsCode);

        // 3.将验证码存储到redis中   ofMinutes分钟  ofMillis毫秒
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + phone, smsCode, Duration.ofMinutes(5));
    }

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @DubboReference
    private UserVoiceService userVoiceService;
    // 注册、登录功能
    public ResponseEntity loginAndRegister(String phone, String verificationCode) {
        // 声明一个返回将结果
        Map<String, Object> resultMap = new HashMap<>();

        // 1.获取redis中验证码
        String codeFromRedis = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        // 2.对比验证码是否一致
        if (!StrUtil.equals(verificationCode, codeFromRedis)) {
            return ResponseEntity.status(500).body(ErrorResult.loginError());
        }
        // 3.根据手机号查询用户
        User user = userService.findByPhone(phone);

        String type;

        if (user != null) { // 老用户
            resultMap.put("isNew", false);
            type = "0101";
        } else {// 新用户
            resultMap.put("isNew", true);
            // 帮新用户注册
            user = new User();
            user.setPhone(phone);
            user.setPassword(ConstantUtil.INIT_PASSWORD);
            Long newUserId = userService.save(user);
            user.setId(newUserId);
            //添加到userVoice表
            UserVoice userVoice = new UserVoice();
            userVoice.setUserId(user.getId());
            userVoice.setRemainingTimes(10);
            userVoiceService.saveUserVoice(userVoice);
            // 注册到环信
            huanXinTemplate.register("HX" + newUserId);

            type = "0102";
        }
        // 4.使用jwt制作令牌
        user.setPassword(null);
        Map<String, Object> claims = BeanUtil.beanToMap(user);
        String token = JwtUtil.createToken(claims);
        // 5.redis存储用户信息
        String json = JSON.toJSONString(user);
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token, json, Duration.ofDays(7));

        // 清除短信验证码
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE + phone);

        // 6.返回结果
        resultMap.put("token", token);

        //判断是否允许登录
        if (findByFreeze(user.getId(), 1)) {
            String time = freezeService.findByFreeze(user.getId()).getFinishTime().toString();
            return ResponseEntity.status(401).body(ErrorResult.freezeByLoginError(DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss")));//401指示请求需要进行 HTTP 验证
        }
        // 7.发送mq的日志消息
        Log log = new Log();
        log.setUserId(user.getId());
        log.setLogTime(DateUtil.formatDate(new Date()));
        log.setPlace("北京顺义");
        log.setEquipment("国产小辣椒");
        log.setType(type);
        rabbitTemplate.convertAndSend("tanhua.log", log);

        return ResponseEntity.ok(resultMap);
    }

    @DubboReference
    private UserInfoService userInfoService;

    // 完善用户基础信息
    public void saveUserInfoBase(UserInfo userInfo, String token) {
        // 1.解析token获取user对象
        User user = findUserByToken(token);
        // 2.给userInfo设置userId
        userInfo.setId(user.getId());
        userInfo.setUserStatus("1");
        // 3.调用rpc保存
        userInfoService.save(userInfo);

    }

    // 解析token获取user对象
    public User findUserByToken(String token) {
        // 1.对token进行非空判断
        if (StrUtil.isEmpty(token)) {
            return null;
        }
        // 2.获取redis中user对象
        String json = stringRedisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);

        // 3.对json进行非空判断
        if (StrUtil.isEmpty(json)) {
            return null;
        }

        // 4.转换为user对象
        User user = JSON.parseObject(json, User.class);

        // 5.对redis的user进行续期
        stringRedisTemplate.opsForValue().set(ConstantUtil.USER_TOKEN + token, json, Duration.ofDays(7));

        return user;
    }

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    // 完善用户头像信息
    public ResponseEntity saveUserInfoHead(MultipartFile headPhoto, String token) throws Exception {
        // 1.解析token获取user对象
        User user = findUserByToken(token);
        // 2.人脸检测
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (detect == false) { // 非人脸
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }
        // 3.上传图片到oss
        String picUrl = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        // 4.组装userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId()); // 用户id
        userInfo.setAvatar(picUrl); // 头像
        userInfo.setCoverPic(picUrl); // 背景
        // 5.调用rpc更新
        userInfoService.update(userInfo);

        return ResponseEntity.ok(null);
    }

    // 查询用户信息
    public ResponseEntity findUserInfoVo(Long id) {
        // 1.调用rpc查询userInfo
        UserInfo userInfo = userInfoService.findUserInfoById(id);
        // 2.封装userInfoVo
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtil.copyProperties(userInfo, userInfoVo);
        // 3.返回
        return ResponseEntity.ok(userInfoVo);
    }

    // 修改用户基础信息
    public void updateUserInfoBase(UserInfo userInfo, String token) {
        // 1.解析token获取user对象
        User user = findUserByToken(token);
        // 2.设置userId到userInfo中
        userInfo.setId(user.getId());
        // 3.调用rpc完成更新
        userInfoService.update(userInfo);
    }

    //发送短信验证码，修改手机号
    public void sendVerificationCode() {
        Long userId = UserHolder.get().getId();
        //通过id查询数据库获得手机号
        User user = userService.findUser(userId);
        // 1.生成6位随机数
        String sendVerificationCode = RandomUtil.randomNumbers(6);
        sendVerificationCode = "123456";
        // 2.将验证码存储到redis中
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + user.getPhone() , sendVerificationCode , Duration.ofMinutes(5));


    }

    //-----------------------------------------------------------------------
    //验证码校验，修改手机号
    public ResponseEntity checkVerificationCode(String verificationCode) {
        // 返回结果
        Map <String, Object> Map = new HashMap <>();
        //获得当前用户id
        Long userId = UserHolder.get().getId();
        //通过id查询数据库获得手机号
        User user = userService.findUser(userId);
        // 1.获取redis中验证码
        String codeFromRedis = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + user.getPhone());
        // 2.对比验证码是否一致
        if (!StrUtil.equals(verificationCode , codeFromRedis)) {
            return ResponseEntity.status(500).body(ErrorResult.loginError());
        }
        // 清除短信验证码
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE + user.getPhone());
        Map.put("verification" , true);
        return ResponseEntity.ok(Map);
    }

    //保存新手机号
    public void savePhone(String phone) {

        Long userId = UserHolder.get().getId();
        //判断手机号是否存在
        User user = userService.findByPhone(phone);
        if (user == null) {
            userService.updatePhone(userId, phone);
        }else{
            int i = 1/0;
        }
    }

    @DubboReference
    private UserLikeService userLikeService;

    /**
     * 互相喜欢，喜欢，粉丝 - 统计
     * @Author: bug
     */
    public ResponseEntity findCount() {
        // 获取线程内用户id
        Long userId = UserHolder.get().getId();
        // 查询喜欢
        Long loves = userLikeService.findLoves(userId);
        // 查询粉丝
        Long fanCount = userLikeService.findFans(userId);
        // 查询互相喜欢
        Long eachLoveCount = userLikeService.findEachLoveCount(userId);

        Map<String, Object> resultMap = new HashMap();
        resultMap.put("eachLoveCount", eachLoveCount);
        resultMap.put("loveCount", loves);
        resultMap.put("fanCount", fanCount);
        return ResponseEntity.ok(resultMap);
    }


    @DubboReference
    private VisitorService visitorService;

    /**
     * 互相喜欢、喜欢、粉丝、谁看过我 - 翻页列表
     * @Author: bug
     */
    public PageBeanVo findFriendsByPage(String type, Integer pageNum, Integer pageSize) {
        // 获取线程内的用户id
        Long userId = UserHolder.get().getId();
        // 根据类型执行不同分页查询
        switch (type) {
            case "1": {
                return userLikeService.findEachLoveByPage(userId, pageNum, pageSize);
            }
            case "2": {
                return userLikeService.findLoveByPage(userId, pageNum, pageSize);
            }
            case "3": {
                return userLikeService.findFanByPage(userId, pageNum, pageSize);
            }
            case "4": {
                return visitorService.findVisitorByPage(userId, pageNum, pageSize);
            }
            default: {
                throw new RuntimeException("访问错误");
            }
        }
    }

    @DubboReference
    private FriendService friendService;

    @DubboReference
    private MovementService movementService;

    /**
     * 喜欢-取消
     * @Author: bug
     */
    public void deleteLike(Long likeUserId) {
        // 获取线程内的用户id
        Long userId = UserHolder.get().getId();
        // rpc调用删除好友
        friendService.deleteContacts(userId, likeUserId);
        // rpc调用删除喜欢
        userLikeService.remove(userId, likeUserId);
        // redis取消喜欢状态
        stringRedisTemplate.delete(StrUtil.format("user_like:{}_{}", userId,likeUserId));
        // rpc调用删除好友动态（好友表中的好友动态和好友好友表中的用户动态）
        movementService.deleteFriendMovement(userId, likeUserId);
        // 删除环信好友
        huanXinTemplate.deleteContacts("HX" + userId, "HX" + likeUserId);
    }

    // 粉丝-喜欢
    public void addLike(Long fanId) {
        // 获取线程内用户id
        Long userId = UserHolder.get().getId();
        // 创建userLike
        UserLike userLike = new UserLike();
        userLike.setCreated(System.currentTimeMillis()); // 操作时间
        userLike.setUserId(userId); // 用户id
        userLike.setLikeUserId(fanId); // 粉丝id
        // rpc调用增加喜欢
        userLikeService.save(userLike);
        // rpc调用添加好友(添加好友动态到用户好友动态表，添加用户动态到好友的好友动态表)
        friendService.addContacts(userId, fanId);
        // 添加环信好友
        huanXinTemplate.addContacts("HX" + userId, "HX" + fanId);

        // redis中存储喜欢状态
        stringRedisTemplate.opsForValue().set(StrUtil.format("user_like:{}_{}", userId,fanId), "1");
    }

    @DubboReference
    private FreezeService freezeService;

    //查询用户是否被冻结
    public Boolean findByFreeze(Long userId, Integer freezingRange) {
        //获取redis中冻结详情
        String freezingRangeByRedis = stringRedisTemplate.opsForValue().get("freeze:" + userId);
        int parseInt = 0;
        if (StrUtil.isNotEmpty(freezingRangeByRedis)) {
            parseInt = Integer.parseInt(freezingRangeByRedis);
        }
        if (StrUtil.isNotEmpty(freezingRangeByRedis)) {//有值
            if (parseInt != freezingRange) {    //但冻结范围不相等
                return false;
            }
        }
        if (StrUtil.isEmpty(freezingRangeByRedis)) {//没值
            //查询是否用户状态
            Freeze byFreeze = freezeService.findByFreeze(userId);
            if(byFreeze!=null&&byFreeze.getUserStatus()==2)freezeService.unFreezeByUserAuto(userId);
            return false;
        }
        return true;
    }
}

